#ifndef MYTINYSTL_CONSTRUCT_H_
#define MYTINYSTL_CONSTRUCT_H_

// 这个头文件包含两个函数 construct，destroy
// construct : 负责对象的构造
// destroy   : 负责对象的析构

#include <new>

#include "iterator.h"
#include "type_traits.h"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4100) // unused parameter
#endif                          // _MSC_VER

namespace mystl {

// construct 构造对象
/**
 *  使用定位 new 表达式在 ptr 指向的内存位置构造一个 Ty 类型的对象，
    调用的是 Ty 类型的默认构造函数。
    ::new ((void*)ptr) Ty() 中的 :: 表示使用全局作用域的 new 运算符，
    (void*)ptr 是将 ptr 强制转换为 void* 类型，这是定位 new 表达式的要求。
 */
template <class Ty> void construct(Ty *ptr) { ::new ((void *)ptr) Ty(); }

template <class Ty1, class Ty2> void construct(Ty1 *ptr, const Ty2 &value) {
  ::new ((void *)ptr) Ty1(value);
}

// 可变参数构造函数版本 万能引用和完美转发  Args... 是一个可变参数模板
template <class Ty, class... Args> void construct(Ty *ptr, Args &&...args) {
  ::new ((void *)ptr) Ty(mystl::forward<Args>(args)...);
}
} // namespace mystl
// destroy 将对象析构

template <class Ty>
void destroy_one(Ty*, std::true_type) {}

template <class Ty>
void destroy_one(Ty* pointer, std::false_type)
{
  if (pointer != nullptr)
  {
    pointer->~Ty();
  }
}

template <class ForwardIter>
void destroy_cat(ForwardIter , ForwardIter , std::true_type) {}

template <class ForwardIter>
void destroy_cat(ForwardIter first, ForwardIter last, std::false_type)
{
  for (; first != last; ++first)
    destroy(&*first);
}

template <class Ty>
void destroy(Ty* pointer)
{
  destroy_one(pointer, std::is_trivially_destructible<Ty>{});
}

template <class ForwardIter>
void destroy(ForwardIter first, ForwardIter last)
{
  destroy_cat(first, last, std::is_trivially_destructible<
              typename iterator_traits<ForwardIter>::value_type>{});
}

// destroy 将对象析构

template <class Ty> void destroy_one(Ty *, std::true_type) {}

template <class Ty> void destroy_one(Ty *pointer, std::false_type) {
  if (pointer != nullptr) {
    pointer->~Ty();
  }
}

template <class ForwardIter>
void destroy_cat(ForwardIter, ForwardIter, std::true_type) {}

template <class ForwardIter>
void destroy_cat(ForwardIter first, ForwardIter last, std::false_type) {
  for (; first != last; ++first)
    destroy(&*first);
}

template <class Ty> void destroy(Ty *pointer) {
  destroy_one(pointer, std::is_trivially_destructible<Ty>{});
}

template <class ForwardIter> void destroy(ForwardIter first, ForwardIter last) {
  destroy_cat(first, last,
              std::is_trivially_destructible<
                  typename iterator_traits<ForwardIter>::value_type>{});
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER

#endif // !MYTINYSTL_CONSTRUCT_H_
